package pl.edu.agh.agents.state;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import pl.edu.agh.agents.agent.Agent;
import pl.edu.agh.agents.agent.SystemManager;
import pl.edu.agh.agents.gui.GUI;
import pl.edu.agh.agents.path.Path;
import pl.edu.agh.agents.planner.Algorithm;
import pl.edu.agh.agents.planner.Dijkstra;

public class StateSpace {
	private final static StateSpace spaceInstance = new StateSpace();
	private List<State> states;
	private Map<Agent, State> goalStates;
	private Map<Agent, State> currentStates;
	private Map<Agent, Path> currentPaths;
	private final Algorithm algorithm = new Dijkstra();

	public static StateSpace getInstance() {
		return spaceInstance;
	}

	private StateSpace(){
		loadGraph(null, GUI.emptyGraphPath);
	}

	public void loadGraph(GUI gui, String filename) {
		states = new ArrayList<State>();

		goalStates = new HashMap<Agent, State>();
		currentStates = new HashMap<Agent, State>();
		currentPaths = new HashMap<Agent, Path>();
	}

	public Map<Agent, State> getGoalStates(){
		return goalStates;
	}

	public Map<Agent, State> getCurrentStates(){
		return currentStates; 
	}

	public Map<Agent, Path> getCurrentPaths(){
		return currentPaths; 
	}

	public void updatePath(Agent agent, Path path){
		currentPaths.remove(agent);
		currentPaths.put(agent, path);
	}

	public Algorithm getAlgorithm() {
		return algorithm;
	}

	public boolean updateState(Agent agent, State state){
		Random random = new Random();
		double enterProb = random.nextDouble();
		if(state.isEmpty() && agent.getCurrentState().getNeighbors().contains(state) && enterProb < state.getEnteringProb()){
			currentStates.remove(agent);
			currentStates.put(agent, state);
			return true;
		}

		return false;
	}

	public List<State> getStates() {
		return states;
	}

	public void addState(State state) {
		states.add(state);
	}

	public void addNeighbor(int srcID, int destID) {
		states.get(srcID).addNeighbor(states.get(destID));
	}

	public void removeNeighbor(int srcID, int destID) {
		states.get(srcID).removeNeighbor(states.get(destID));
	}

	public void addGoalState(Agent agent, State state) {
		if (!state.isSink()) {
			goalStates.put(agent, state);
		}
	}

	public void removeState(State state) {
		if (state == null) {
			return;
		}

		states.remove(state);

		Agent agent = state.getAgent();

		if (state.getAgent() != null) {
			SystemManager.getInstance().removeAgent(agent);
			removeGoalState(agent);
			currentStates.remove(agent);
			currentPaths.remove(agent);
		}
	}

	public void removeGoalState(Agent agent) {
		goalStates.remove(agent);

	}
}